package com.atguigu.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.atguigu.base.BaseDAO;
import com.atguigu.base.BaseServiceImpl;
import com.atguigu.dao.PermissionDAO;
import com.atguigu.dao.RolePermissionDAO;
import com.atguigu.entity.Permission;
import com.atguigu.entity.RolePermission;
import com.atguigu.helper.PermissionHelper;
import com.atguigu.service.PermissionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @PACKAGE_NAME: com.atguigu.service.impl
 * @CLASSNAME: PermissionServiceImpl
 * @AUTHOR: zhangsan
 * @DATE: 2024/5/1 21:00
 * @SINCE 17.0.7
 * @DESCRIPTION: PermissionServiceImpl
 */
@Slf4j
@Service(interfaceClass = PermissionService.class)
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class PermissionServiceImpl extends BaseServiceImpl<Permission> implements PermissionService {

    @Resource
    private PermissionDAO permissionDAO;

    @Resource
    private RolePermissionDAO rolePermissionDAO;

    @Override
    protected BaseDAO<Permission> getEntityDAO() {
        return permissionDAO;
    }

    /**
     * 根据角色id,获取该角色拥有的权限
     *
     * @param roleId
     * @return
     */
    @Override
    public List<Map<String, Object>> findPermissionByRoleId(Long roleId) {
        //var zNodes =[
        //			{ id:1, pId:0, name:"随意勾选 1", open:true},
        //			{ id:11, pId:1, name:"随意勾选 1-1"},
        //			{ id:12, pId:1, name:"随意勾选 1-2", open:true},
        //			{ id:121, pId:12, name:"随意勾选 1-2-1"},
        //			{ id:122, pId:12, name:"随意勾选 1-2-2"},
        //			{ id:2, pId:0, name:"禁止勾选 2", open:true, doCheck:false},
        //			{ id:21, pId:2, name:"禁止勾选 2-1", doCheck:false},
        //			{ id:22, pId:2, name:"禁止勾选 2-2", checked:true, open:true, doCheck:false},
        //			{ id:221, pId:22, name:"禁止勾选 2-2-1", doCheck:false},
        //			{ id:222, pId:22, name:"禁止勾选 2-2-2", checked:true, doCheck:false},
        //			{ id:23, pId:2, name:"禁止勾选 2-3", doCheck:false}
        //		];
        //通过roleId找到所有的PermissionId
        //遍历所有的permissionId,将该roleId拥有的permissionId的对应的ztree树中的checked属性置为true
        //所有的父节点的open属性都为true,所有的子节点都有checked属性
        //checked属性表示是否勾选该选框,doCheck属性表示是否禁用该选框,前者能点后者不能点,焊死了
        List<Permission> allPermissionList = permissionDAO.findAll();
        List<Long> assignedPermissionIds = rolePermissionDAO.findPermissionIdsByRoleId(roleId, 0);
        Map<Boolean, List<Permission>> collect = allPermissionList.stream().collect(Collectors.partitioningBy(permission -> assignedPermissionIds.contains(permission.getId())));
        List<Permission> assignedPermissions = collect.get(true);
        List<Permission> noAssignedPermissions = collect.get(false);

        List<Map<String, Object>> zNodes = new ArrayList<>();
        assignedPermissions.forEach(assignedPermission -> {
            //Map<String, Object> zNode = new HashMap<>();
            //Long id = assignedPermission.getId();
            //Integer parent = permissionDAO.isParent(id);
            //zNode.put("id", id);
            //zNode.put("pId", assignedPermission.getParentId());
            //zNode.put("name", assignedPermission.getName());
            //zNode.put("open", parent > 0);
            //zNode.put("checked", true);
            Map<String, Object> zNode = putZNode(assignedPermission, true);
            zNodes.add(zNode);
        });
        //测试通过之后,抽取代码
        noAssignedPermissions.forEach(noAssignedPermission -> {
            //Map<String, Object> zNode = new HashMap<>();
            //Long id = noAssignedPermission.getId();
            //Integer parent = permissionDAO.isParent(id);
            //zNode.put("id", id);
            //zNode.put("pId", noAssignedPermission.getParentId());
            //zNode.put("name", noAssignedPermission.getName());
            //zNode.put("open", parent > 0);
            //zNode.put("checked", false);
            Map<String, Object> zNode = putZNode(noAssignedPermission,false);
            zNodes.add(zNode);
        });
        return zNodes;
    }

    /**
     * 抽取方法往zNode里面放数据
     * @param permission
     * @return
     */
    private Map<String, Object> putZNode(Permission permission, Boolean checked) {
        Map<String, Object> zNode = new HashMap<>();
        Long id = permission.getId();
        Integer parent = permissionDAO.isParent(id);
        zNode.put("id", id);
        zNode.put("pId", permission.getParentId());
        zNode.put("name", permission.getName());
        zNode.put("open", parent > 0);
        zNode.put("checked", checked);
        return zNode;
    }

    /**
     * 给角色分配权限,其实就是将角色与权限关系保存在acl_role_permission中间表中
     *
     * @param roleId
     * @param permissionIds
     */
    @Override
    public void assignPermissionsToRole(Long roleId, Long[] permissionIds) {
        //清空之前给该角色分配的权限,从permissionIds中重新分配
        RolePermission rolePermission = new RolePermission();
        rolePermission.setPermissionId(null);
        rolePermission.setRoleId(roleId);
        rolePermission.setIsDeleted(1);
        Integer i = rolePermissionDAO.updateIsDeletedByRoleIdAndPermissionId(rolePermission);
        log.debug("i = {}", i);

        List<Long> permissionIdsWithoutIsDeleted = rolePermissionDAO.findPermissionIdsByRoleId(roleId, null);
        //如果该权限之前给该角色分配过,则修改acl_role_permission表中的isDeleted字段即可
        Map<Boolean, List<Long>> collect = Arrays.stream(permissionIds).collect(Collectors.partitioningBy(permissionIdsWithoutIsDeleted::contains));
        List<Long> everAssignedPermissionIds = collect.get(true);
        everAssignedPermissionIds.forEach(permissionId -> {
            RolePermission rolePermission1 = new RolePermission();
            rolePermission1.setRoleId(roleId);
            rolePermission1.setPermissionId(permissionId);
            rolePermission1.setIsDeleted(0);
            Integer i1 = rolePermissionDAO.updateIsDeletedByRoleIdAndPermissionId(rolePermission1);
            log.debug("i1 = {}", i1);
        });
        List<Long> noAssignedPermissionIds = collect.get(false);

        //如果该权限之前没有分配给该角色,则在acl_role_permission表中新增一条记录即可
        noAssignedPermissionIds.forEach(permissionId -> {
            RolePermission rolePermission2 = new RolePermission();
            rolePermission2.setId(null);
            rolePermission2.setRoleId(roleId);
            rolePermission2.setPermissionId(permissionId);
            Integer i2 = rolePermissionDAO.insert(rolePermission2);
            log.debug("i2 = {}", i2);
        });
    }

    /**
     * 获取用户菜单权限,通过用户id获取用户角色,根据角色获取该角色分配的权限
     *
     * @param adminId
     * @return
     */
    @Override
    public List<Permission> findMenuPermissionByAdminId(Long adminId) {
        List<Permission> permissionList = null;
        //admin账号的id为1,直接进行比较
        if (adminId.intValue() == 1) {
            //如果是admin,超级管理员(系统管理员),获取所有菜单
            permissionList = permissionDAO.findAllMenu();
        } else {
            //type=1表示菜单,type=2表示按钮
            permissionList = permissionDAO.findPermissionListByAdminId(adminId, 1);
        }

        //将List<Permission>通过id和parentId的关系进行分级
        List<Permission> result = PermissionHelper.bulid(permissionList);
        return result;
    }



    /**
     * 找到所有的权限,并分级
     * @return
     */
    @Override
    public List<Permission> findAllMenuPermission() {
        List<Permission> allPermission = permissionDAO.findAll();
        if (CollectionUtils.isEmpty(allPermission)) return null;
        List<Permission> hierarchicalMenu = PermissionHelper.bulid(allPermission);
        return hierarchicalMenu;
    }

    /**
     * 如果曾经存在,只是被删除了 is_deleted = 1,则将is_deleted改为0即可,
     * 如果曾经不存在,则进行修改
     *
     * @param permission
     */
    @Override
    public Boolean updateIfEverExisted(Permission permission) {
        permission.setIsDeleted(null);
        Permission existedPermission = permissionDAO.selectByTypeNameUrlCode(permission);
        if (null == existedPermission) {
            Integer i = permissionDAO.update(permission);
            return true;
        } else {
            if (existedPermission.getIsDeleted() == 1) {
                Integer i = permissionDAO.updateIsDeleted(existedPermission.getId(), 0);
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 如果曾经存在,只是被删除了 is_deleted = 1,则将is_deleted改为0即可,
     * 如果曾经不存在,则进行新增.
     *
     * @param permission
     */
    @Override
    public Boolean insertIfEverExisted(Permission permission) {
        permission.setIsDeleted(null);
        Permission existedPermission = permissionDAO.selectByTypeNameUrlCode(permission);
        if (null == existedPermission) {
            Integer i = permissionDAO.insert(permission);
            return true;
        } else {
            if (existedPermission.getIsDeleted() == 1) {
                Integer i = permissionDAO.updateIsDeleted(existedPermission.getId(), 0);
                return true;
            } else {
                return false;
            }
        }
    }

    @Override
    public Permission selectByTypeNameUrlCode(Permission permission) {
        permission.setIsDeleted(0);
        Permission permission1 = permissionDAO.selectByTypeNameUrlCode(permission);
        return permission1;
    }

    /**
     * 通过用户id查找用户所拥护权限的权限编码code集合
     * 注意,只有按钮type=1才有权限编码code,菜单type=2对应的是菜单url
     *
     * @param adminId
     * @return
     */
    @Override
    public List<String> findCodeListByAdminId(Long adminId) {
        //admin账号id为1,直接进行比较
        List<String> codeList = null;
        if (adminId.intValue() == 1) {
            //如果是admin,超级管理员(系统管理员)拥有所有权限
            codeList = permissionDAO.findAllCodeList();
        } else {
            //通过adminId查找该用户拥有的权限
            codeList = permissionDAO.findCodeListByAdminId(adminId);
        }

        return codeList;
    }
}
